#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "circle_buffer.h"

sj_int8 circle_buffer_create(circle_buffer_info *info,sj_int8 item_size, sj_int8 item_num)
{
	sj_int8 ret =0;

	info->item_size = item_size;
	info->item_num = item_num;
	info->read  = 0;
	info->full  = 0;
	info->write = 0;
	info->size  =item_size*item_num ;
	info->item_ptr = malloc(item_size*item_num);
	memset(info->item_ptr,0,info->size);
	return ret;

}

sj_int8 circle_buffer_destory(circle_buffer_info *info)
{
	sj_int8 ret =0;

	free(info->item_ptr);

	return ret;
}

sj_int8 circle_buffer_clear(circle_buffer_info *info)
{
	sj_int8 ret =0;

	info->read  =0;
	info->write =0;

	memset(info->item_ptr,0,info->size);
	
	return ret;
}

sj_int32 circle_buffer_get_num(circle_buffer_info *info)
{
	sj_int32 len =0;
	if(info->write >= info->read)
	{
		len =info->write  - info->read; 
	}
	else{
		len = info->size - info->read + info->write; 
	}

	return len;
}


sj_int8 circle_buffer_write(circle_buffer_info *info,sj_void  *data ,sj_int32 len)
{
	sj_int8 ret =0;

	sj_void *dest = info->item_ptr + info->write;

	if(info->write + len < info->size)
	{
		memcpy(dest,data,len);
	}
	else
	{
		memcpy(dest,data,info->size-info->write);

		sj_void *src = data + info->size-info->write;

		memcpy(info->item_ptr,src,info->write + len - info->size);
	}
	
	info->write = (info->write+len)%info->size;
	//printf("write %d  read %d \n",info->write,info->read);
	return ret;
}

sj_int8 circle_buffer_read(circle_buffer_info *info,sj_void  *data ,sj_int32 len)
{

	sj_void *src = info->item_ptr + info->read;

	if( (info->read+len)%info->size > info->write)
	{
		if(info->read > info->write)
		{
			len = info->size  - info->read + info->write;
		}
		else
		{
			len = info->write - info->read;
		}
	}

	if(info->read + len < info->size)
	{
		memcpy(data,src,len);
	}
	else
	{
		memcpy(data,src,info->size-info->read);

		sj_void *dest = data + info->size-info->read;

		memcpy(dest,info->item_ptr,info->read + len - info->size);
	}
	
	info->read = (info->read+len)%info->size;

	return len;
}

sj_int8 circle_buffer_is_empty(circle_buffer_info *info)
{
	if(info->read == info->write)
	{
		return 1;
	}
	return 0;
}
sj_int32 circle_buffer_set_read(circle_buffer_info *info,sj_int32 index)
{
	if(info->read <=info->write)
	{
		if(index <=info->write)
		{
			info->read = index;
			return 0;
		}
	}
	else
	{
		if(index>=info->read || index<= info->write)
		{
			info->read = index;
			return 0;
		}
	}
	return -1;
}
